//Sekce obsahujici dodefinovani tridy Qpodminka:

#include "beh.h"
#include "pamet.h"
extern Bpromsez *obsah(char *o,Bpromsez *s);
extern Qstrom *NIL;

int Qdisjunkce::over(Bpromsez *ps){
  return (p1->over(ps)||p2->over(ps));
}

int Qkonjunkce::over(Bpromsez *ps){
  return (p1->over(ps)&&p2->over(ps));
}

int Qnegace::over(Bpromsez *ps){
  return !p->over(ps);
}

void podm_vyhodnoceni(Bhodnota &h,Bpromsez *ps){
  Qstrom *p;
  if(!h.d){
    h.s=NULL;
    while(!h.s&&h.v) switch(h.v->vkonst()){
      case _Latom:
        h.s=h.v->vobsah();
        h.q=h.v->vsyn();
        break;
      case _Latomovapromenna:
        p=obsah(h.v->vobsah(),ps)->obsah;
        h.s=p->vobsah();
        h.q=h.v->vsyn();
        break;
      case _Lstromovapromenna:
        p=obsah(h.v->vobsah(),ps)->obsah;
        h.s=p->vobsah();
        h.q=p->vsyn();
        break;
      case _Lseznamovapromenna:
        p=obsah(h.v->vobsah(),ps)->obsah;
        if(p==NIL){
          h.v=h.v->vbratr();
        }else{
          h.r=h.v->vbratr();
          h.v=p;
        }
        break;
      case _Ldekompozice:
        p=obsah(h.v->vdesint()->vobsah(),ps)->obsah;
        h.d=1;
        h.s=p->vobsah();
        break;
      case _Lnul:
        h.v=h.v->vbratr();
        break;
    }
  }
}

void podm_krok(Bhodnota &h){
  if(h.d){
    h.s++;
    if(!*h.s) h.d=0;
  }
  if(!h.d){
    h.v=h.v->vbratr();
    if(!h.v&&h.r){
      h.v=h.r;
      h.r=NULL;
    }
  }
}

int Qrovnost::over(Bpromsez *ps){
  Bhodnota h[2];
  int i;
  h[0].v=u1;h[1].v=u2;
  h[0].r=h[1].r=NULL;
  h[0].d=h[1].d=0;
  while(h[0].v&&h[1].v){
    for(i=0;i<2;i++) podm_vyhodnoceni(h[i],ps);
    if(!(h[0].v&&h[1].v)) break;
    if(h[0].d){
      if(h[1].d){
        if(*h[0].s!=*h[1].s) return 0;
      }else{
        if(strlen(h[1].s)!=1||*h[0].s!=*h[1].s) return 0;
        Bhodnota g;
        g.v=h[1].q;
        g.r=NULL;
        g.d=0;
        podm_vyhodnoceni(g,ps);
        if(g.v) return 0;
      }
    }else{
      if(h[1].d){
        if(strlen(h[0].s)!=1||*h[0].s!=*h[1].s) return 0;
        Bhodnota g;
        g.v=h[0].q;
        g.r=NULL;
        g.d=0;
        podm_vyhodnoceni(g,ps);
        if(g.v) return 0;
      }else{
        if(strcmp(h[0].s,h[1].s)) return 0;
        Qrovnost *Qr=new Qrovnost(h[0].q,h[1].q);
        malopameti(Qr);
        i=Qr->over(ps);
        if(h[0].q) h[0].q->pocplus(); // opravil PH 27.3.2001
        if(h[1].q) h[1].q->pocplus(); // opravil PH 27.3.2001
        delete Qr;
        if(!i) return 0;
      }
    }
    for(i=0;i<2;i++) podm_krok(h[i]);
  }
  for(i=0;i<2;i++) podm_vyhodnoceni(h[i],ps);
  if(h[0].v||h[1].v) return 0;
  return 1;
}

int Qnerovnost::over(Bpromsez *ps){
  Qrovnost *Qr=new Qrovnost(u1,u2);
  malopameti(Qr);
  u1->pocplus();
  u2->pocplus();
  int i=Qr->over(ps);
  delete Qr;
  return !i;
}

int Qdans::over(Bpromsez *ps){
  if(u1==NIL) return 1;
  if(u2==NIL) return 0;
  Bhodnota h1,h2;
  h1.r=h2.r=NULL;
  h1.d=h2.d=0;
  h1.v=u1;
  podm_vyhodnoceni(h1,ps);
  while(h1.v){
    int i=0;
    h2.r=NULL; //toto zde chybelo (11.6.2001)
    h2.d=0;    //toto zde chybelo (11.6.2001)
    h2.v=u2;
    podm_vyhodnoceni(h2,ps);
    while(h2.v&&!i){
      if(h1.d){
        if(h2.d){
          i=(*h1.s==*h2.s);
        }else{
          if(strlen(h2.s)==1&&*h1.s==*h2.s){
/*            Bhodnota g;
            g.v=h2.q;
            g.r=NULL;
            g.d=0;
            podm_vyhodnoceni(g,ps);
            if(g.v)*/ i=1;          //zde byla asi chyba (11.6.2001)
          }
        }
      }else{
        if(h2.d){
          if(strlen(h1.s)==1&&*h1.s==*h2.s){
            Bhodnota g;
            g.v=h1.q;
            g.r=NULL;
            g.d=0;
            podm_vyhodnoceni(g,ps);
            if(!g.v) i=1;//zde nebyl ! v podmince //zde byla asi chyba (11.6.2001)
          }
        }else{
          if(!strcmp(h1.s,h2.s)){
            Qdans *Qd=new Qdans(h1.q,h2.q);
            malopameti(Qd);
            if(h1.q) h1.q->pocplus(); // opravil PH 27.3.2001
            if(h2.q) h2.q->pocplus(); // opravil PH 27.3.2001
            i=Qd->over(ps);
            delete Qd;
          }
        }
      }
      podm_krok(h2);
      podm_vyhodnoceni(h2,ps);
    }
    if(!i) return 0;
    podm_krok(h1);
    podm_vyhodnoceni(h1,ps);
  }
  return 1;
}

int Qhors::over(Bpromsez *ps){
  if(u1==NIL||u2==NIL) return 0;
  Bhodnota h1,h2;
  h1.r=h2.r=NULL;
  h1.d=h2.d=0;
  h1.v=u1;
  podm_vyhodnoceni(h1,ps);
  h2.v=u2;
  podm_vyhodnoceni(h2,ps);
  if(!(h1.v&&h2.v)) return 0;
  h1.r=h2.r=NULL;
  h1.d=h2.d=0;
  h1.v=u1;
  podm_vyhodnoceni(h1,ps);
  while(h1.v){
    h2.r=NULL; //toto zde chybelo (11.6.2001)
    h2.d=0;    //toto zde chybelo (11.6.2001)
    h2.v=u2;
    podm_vyhodnoceni(h2,ps); // opravil PH 27.3.2001
    while(h2.v){
      if(h1.d){
        if(h2.d){
          if(*h1.s==*h2.s) return 0;
        }else{
          if(strlen(h2.s)==1&&*h1.s==*h2.s) return 0;
        }
      }else{
        if(h2.d){
          if(strlen(h1.s)==1&&*h1.s==*h2.s) return 0;
        }else{
	  // nasledujici podminky prepsal PH 2.12.2003
	  int stromy = h1.q && h2.q;
	  int stejne = !strcmp(h1.s, h2.s);
          if(stromy) {
	   if(stejne) {
             Qhors *Qh=new Qhors(h1.q,h2.q);
             malopameti(Qh);
             if(h1.q) h1.q->pocplus(); // opravil PH 27.3.2001
             if(h2.q) h2.q->pocplus(); // opravil PH 27.3.2001
             int i=Qh->over(ps);
             delete Qh;
             if(!i) return 0;
           }
          }
	  if (!stromy && stejne) return 0;
        }
      }
      podm_krok(h2);
      podm_vyhodnoceni(h2,ps);
    }
    podm_krok(h1);
    podm_vyhodnoceni(h1,ps);
  }
  return 1;
}

